#! /usr/bin/env python
"""
::BOH
$Id: monitor.py,v 1.3 2006/04/19 01:20:00

Copyright (c) 2006 George Bobeck. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
::EOH

OWTF data monitor daemon.

You must be running OWFS for this to work.
All temperatures are in degrees C.
"""
import pickle
import sys, os 
import ow
"""
Deprecated:
from reading import *
"""
from OWTFparser import *
from socket import *
from time import *
from datetime import *

def conf(location):
    f = open(location,'r')
    a = f.readlines()
    fl = []
    var_list = []
    for e in a:
        if "#" not in e:
            e = e.strip('\n')
            e = e.strip('\r')
            if e == '':
                pass
            else:
                e = e.split("\t")
                try:
                    e.remove('')
                except:
                    pass
            var_list.extend(e)
    return var_list

confs = conf(sys.argv[ 1 ])

# Notes on host:
# "224.0.0.1" = MULTICAST address, send to all on subnet
# "" = localhost
# "<address>" = sends to that address.  
verbose = bool(confs[confs.index("verbose")+1])
host = confs[confs.index("host")+1]
port = int(confs[confs.index("port")+1])
buf = 1024
addr = ( host,port )
UDPSock = socket( AF_INET,SOCK_DGRAM ) # Create UDP Socket
ID = confs[confs.index("ID")+1]
OWsource = confs[confs.index("OWsource")+1]
sensors_conf = confs[confs.index("sensors_conf")+1]
resolution = int(confs[confs.index("resolution")+1])
if verbose:
    print "Verbose Mode Enabled"
    print "host: ",host
    print "port: ", port
    print "Monitor ID: ",ID
    print "OWFS source: ",OWsource
    print "Sensors.conf at: ",sensors_conf
    print "Resolution (in senconds): ",resolution
#host = '224.0.0.1'
#port = 50000
#ID = "Monitor 1"
#OWsource = "/dev/ttyS0"
#sensors_conf = '/code/weather/owtf/sensors.conf'
#resolution = 300 #number of SECONDS, for sleep()

# This version of monitor is limited to the following Chips / Family codes:
# "DS1920":10,"DS18S20":10,"DS1921":21,"DS1822":22,"DS2438":26,"DS2436":1B
types = ( "DS1920","DS18S20","DS1921","DS1822","DS2438","DS2436" )
ad = {}

def monitor( ):
    global ad
    root = ow.Sensor( '/' )
    for sensor in root.find( all=True ):
        st = sensor._type
        if st in types:
            a = Reading()
            tm = datetime.today()
            tm = tm.strftime( "%Y-%m-%d %H:%M:%S" ) # YYYY-MM-DD HH:MM:SS  
            ct = float( sensor.temperature )
            a.SetMID( ID )
            a.SetSID( sensor.address)
            a.SetLocation( ad[str(sensor.address)])
            a.SetTime( tm )
            a.SetTemp( ct )
            # Change in future version, make fully functional
            try:
                if sensor.humidity < 100 and sensor.humidity > 0.0:
                    a.SetHumid( sensor.humidity)
                else:
                    a.SetHumid(0.0)
            except:
                a.SetHumid( 0.0 )
            # Unused at this point.  For Future Feature Expansion
            a.SetV1(0.0)
            a.SetV2(0.0)
            # ---
            data2 = pickle.dumps( a )
            UDPSock.sendto( data2,addr )
        else:
            print >>sys.stderr, "OOPS: Sensor Not Supported!!"

def sensconf():
    
    f = open(sensors_conf,'r')
    sl = f.readlines()
    global ad
    ad = {}
    for s in sl:
        if "#" not in s:
            s = s.strip('\n')
            s2 = s.split('\t')
            if len(s2) == 2:
                ad[s2[0]] = s2[1]
            else:
                pass
        else:
            pass

def main():
    sensconf()
    while 1:
        ow.init( OWsource )
        monitor( )
        sleep( resolution )

if __name__ == "__main__":
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit first parent
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "ERROR: fork #1 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1)

    # decouple from parent environment
    os.chdir("/") 
    os.setsid() 
    os.umask(0) 

    # do second fork
    try: 
        pid = os.fork() 
        if pid > 0:
            # exit from second parent, print eventual PID before
            if verbose:
                print "Monitor PID %d" % pid 
            sys.exit(0) 
    except OSError, e: 
        print >>sys.stderr, "ERROR: fork #2 failed: %d (%s)" % (e.errno, e.strerror) 
        sys.exit(1) 

    # start the daemon main loop
    main() 
